﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using HalconDotNet;

namespace Kimd.Vision
{
    [Serializable]
    public class PolygonNB : ShapeNB
    {
        private HTuple _row, _col;
        public List<PointF> Points;
        public PolygonNB()
            : base()
        {
            TypeName = ShapeType.Polygon;
            Points = new List<PointF>();
        }
        public PolygonNB(PolygonNB polygon)
        {
            
        }
        public override void Draw(HWindow window, Graphics g, Func<PointF, PointF> pixel2Window, Func<float, float> lenConvert, bool disableEdit)
        {
            if (disableEdit)
            {
                window.SetColor(PaintColor);
                window.SetLineWidth(LineWidth);
                window.SetDraw("margin");
                List<float> pointsX = new List<float>();
                List<float> pointsY = new List<float>();
                Points.ForEach(p => { pointsX.Add(p.X); pointsY.Add(p.Y); });
                window.DispPolygon(new HTuple(pointsY.ToArray()), new HTuple(pointsX.ToArray()));
            }
            else
            {
                if (!IsSelected)
                {
                    window.SetColor(PaintColor);
                    window.SetLineWidth(LineWidth);
                    window.SetDraw("margin");
                    List<float> pointsX = new List<float>();
                    List<float> pointsY = new List<float>();
                    Points.ForEach(p => { pointsX.Add(p.X); pointsY.Add(p.Y); });
                    window.DispPolygon(new HTuple(pointsY.ToArray()), new HTuple(pointsX.ToArray()));
                    HRegion reg = new HRegion();
                    reg.GenRegionPolygonFilled(new HTuple(pointsY.ToArray()), new HTuple(pointsX.ToArray()));
                    reg.AreaCenter(out _row, out _col);
                    window.SetColor("yellow");
                    float size = lenConvert(5);
                    window.DispRectangle2(_row.D, _col.D, 0, size, size);
                    reg.Dispose();
                }
                else
                {
                    window.SetColor("orange");
                    window.SetLineWidth(1);
                    window.SetDraw("margin");
                    List<float> _pointsX = new List<float>();
                    List<float> _pointsY = new List<float>();
                    Points.ForEach(p => { _pointsX.Add(p.X); _pointsY.Add(p.Y); });
                    window.DispPolygon(new HTuple(_pointsY.ToArray()), new HTuple(_pointsX.ToArray()));
                    HRegion reg = new HRegion();
                    reg.GenRegionPolygonFilled(new HTuple(_pointsY.ToArray()), new HTuple(_pointsX.ToArray()));
                    reg.AreaCenter(out _row, out _col);
                    window.SetColor("red");
                    float size = lenConvert(5);
                    window.DispRectangle2(_row.D, _col.D, 0, size, size);
                    reg.Dispose();
                }
            }
        }
        public override void Change(PointF point)
        {
            switch (ChangeModel)
            {
                case PositionNB.In:
                    List<PointF> pts = new List<PointF>(Points.ToArray());
                    Points.Clear();
                    float dx = point.X - (float)_col.D;
                    float dy = point.Y - (float)_row.D;
                    for (int i = 0; i < pts.Count; i++)
                    {
                        Points.Add(new PointF(pts[i].X + dx, pts[i].Y + dy));
                    }
                    break;
                case PositionNB.Create:
                    this.Points.Add(point);
                    break;
            }
        }
        public override PositionNB PointOnShape(PointF point, Func<float, float> lenConvert)
        {
            if (_col == null || _row == null)
                return PositionNB.Out;

            distance2Handle = (int)lenConvert(10);

            double dcenter = DistancePp(point, new PointF((float)_col.D, (float)_row.D));
            if (dcenter < distance2Handle)
                return PositionNB.In;
            return PositionNB.Out;
        }
        public override HObject ToRegion()
        {
            HRegion reg = new HRegion();
            List<float> _pointsX = new List<float>();
            List<float> _pointsY = new List<float>();
            Points.ForEach(p => { _pointsX.Add(p.X); _pointsY.Add(p.Y); });
            reg.GenRegionPolygonFilled(new HTuple(_pointsY.ToArray()), new HTuple(_pointsX.ToArray()));
            return reg;
        }
        public override void ToXmlNode(out Dictionary<string, object> attributes, out Dictionary<string, object> nodes)
        {
            attributes = new Dictionary<string, object>();
            attributes.Add("Color", PaintColor);
            attributes.Add("LineWidth", LineWidth);
            attributes.Add("Type", TypeName.ToString());
            attributes.Add("Operator", RegOperator.ToString());

            nodes = new Dictionary<string, object>();
            for(int i = 0; i< Points.Count; i++)
            {
                nodes.Add("Point" + i, Points[i].X.ToString("0.000") + "," + Points[i].Y.ToString("0.000"));
            }

            nodes.Add("Alias", string.IsNullOrEmpty(Alias) ? "" : Alias);
        }
        public override void FromXmlNode(XmlNode node)
        {
            RegOperator = (ShapeOperator)Enum.Parse(typeof(ShapeOperator), node.Attributes["Operator"].Value);
            PaintColor = node.Attributes["Color"].Value;
            LineWidth = Int32.Parse(node.Attributes["LineWidth"].Value);

            foreach(XmlNode n in node.ChildNodes)
            {
                if(n.Name.Contains("Point"))
                {
                    Points.Add(new PointF(float.Parse(n.InnerText.Split(',')[0]), float.Parse(n.InnerText.Split(',')[1])));
                }
                else if(n.Name == "Alias")
                {
                    Alias = n.InnerText;
                }
            }
        }
    }
}
